package org.chartsy.forexfeed;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import java.util.prefs.Preferences;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.chartsy.main.data.DataItem;
import org.chartsy.main.data.DataProvider;
import org.chartsy.main.data.Dataset;
import org.chartsy.main.data.Stock;
import org.chartsy.main.data.StockNode;
import org.chartsy.main.data.StockSet;
import org.chartsy.main.exceptions.InvalidStockException;
import org.chartsy.main.exceptions.RegistrationException;
import org.chartsy.main.exceptions.StockNotFoundException;
import org.chartsy.main.intervals.CustomInterval;
import org.chartsy.main.intervals.Interval;
import org.chartsy.main.managers.DatasetUsage;
import org.chartsy.main.managers.ProxyManager;
import org.chartsy.main.utils.NotifyUtil;
import org.chartsy.main.utils.SerialVersion;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
public class ForexFeedChartsy extends DataProvider
{
public ForexFeedChartsy()
{
super(NbBundle.getBundle(ForexFeedChartsy.class), true, true);
Preferences pref = NbPreferences.forModule(ForexFeedPanel.class);
this.ACCESS_KEY = pref.get("access_key", "");
this.needsRegistration = true;
this.isRegistered = !ACCESS_KEY.isEmpty();
this.refreshInterval = pref.getInt("refresh_interval", 5);
}
@Override
public boolean supportsAnyInterval()
{
return false;
}
@Override
public Interval[] getSupportedIntervals()
{
return supportedIntervals;
}
@Override
public int getRefreshInterval()
{
return refreshInterval;
}
@Override
public StockSet fetchAutocomplete(String text)
throws IOException
{
String url = "http://fxf.forexfeed.net/symbols/CHARTSY-" + ACCESS_KEY;
StockSet result = new StockSet();
final HttpClient client = ProxyManager.getDefault().getHttpClient();
final GetMethod method = new GetMethod(url);
client.executeMethod(method);
InputStream inputStream = method.getResponseBodyAsStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String inputLine;
int i = 0;
while ((inputLine = bufferedReader.readLine()) != null)
{
if (i > 0)
{
StringTokenizer st = new StringTokenizer(inputLine, ",");
String key = st.nextToken();
String company = st.nextToken();
String exchange = "FOREX";
if (key.toLowerCase().contains(text.toLowerCase()))
{
result.add(new StockNode(key, company, exchange));
}
}
i++;
}
bufferedReader.close();
method.releaseConnection();
return result;
}
@Override
protected DataItem fetchLastDataItem(Stock stock, Interval interval)
throws IOException, ParseException
{
synchronized ((stock.toString() + "-" + interval.getTimeParam()).intern())
{
DataItem dataItem = null;
BufferedReader bufferedReader = null;
String uri = getLastDataURL(1, stock, interval);
bufferedReader = ProxyManager.getDefault().bufferReaderGET(uri);
String inputLine;
boolean startOnNext = false;
while ((inputLine = bufferedReader.readLine()) != null)
{
if (inputLine.contains("Accesses remaining in this period"))
{
String accesses = inputLine.split(",", 2)[1].replace("\"", "");
accessesRemaining = Integer.parseInt(accesses);
if (accessesRemaining < 1)
{
NotifyUtil.warn("Accesses remaining", "You have no more accesses remaining", false);
return null;
}
}
if (inputLine.equals("QUOTE END"))
{
startOnNext = false;
break;
}
if (startOnNext)
{
String[] values = inputLine.split(",");
if (values.length > 6)
{
long time = Long.parseLong(values[2]) * 1000;
double open = Double.parseDouble(values[3]);
double high = Double.parseDouble(values[4]);
double low = Double.parseDouble(values[5]);
double close = Double.parseDouble(values[6]);
double volume = 0d;
dataItem = new DataItem(time, open, high, low, close, volume);
}
}
if (inputLine.equals("QUOTE START"))
{
startOnNext = true;
continue;
}
}
bufferedReader.close();
return dataItem;
}
}
@Override
public List<DataItem> getLastDataItems(Stock stock, Interval interval)
{
synchronized ((stock.toString() + "-" + interval.getTimeParam()).intern())
{
try
{
List<DataItem> dataItems = new ArrayList<DataItem>();
BufferedReader bufferedReader = null;
String uri = getLastDataURL(getPeriods(interval), stock, interval);
bufferedReader = ProxyManager.getDefault().bufferReaderGET(uri);
String inputLine;
boolean startOnNext = false;
while ((inputLine = bufferedReader.readLine()) != null)
{
if (inputLine.contains("Accesses remaining in this period"))
{
String accesses = inputLine.split(",", 2)[1].replace("\"", "");
accessesRemaining = Integer.parseInt(accesses);
if (accessesRemaining < 1)
{
NotifyUtil.warn("Accesses remaining", "You have no more accesses remaining", false);
return null;
}
}
if (inputLine.equals("QUOTE END"))
{
startOnNext = false;
break;
}
if (startOnNext)
{
String[] values = inputLine.split(",");
if (values.length > 6)
{
long time = Long.parseLong(values[2]) * 1000;
double open = Double.parseDouble(values[3]);
double high = Double.parseDouble(values[4]);
double low = Double.parseDouble(values[5]);
double close = Double.parseDouble(values[6]);
double volume = 0d;
DataItem dataItem = new DataItem(time, open, high, low, close, volume);
dataItems.add(dataItem);
}
}
if (inputLine.equals("QUOTE START"))
{
startOnNext = true;
continue;
}
}
bufferedReader.close();
Collections.sort(dataItems);
return dataItems;
} catch (Exception ex)
{
return new ArrayList<DataItem>();
}
}
}
@Override
public boolean updateIntraDay(String key, List<DataItem> dataItems)
{
DatasetUsage datasetUsage = DatasetUsage.getInstance();
int lastIndex = datasetUsage.getDatasetFromMemory(key).getLastIndex();
int last = dataItems.size() - 1;
DataItem oldItem = datasetUsage.getDatasetFromMemory(key).getLastDataItem();
if (oldItem.getTime() == dataItems.get(last).getTime())
{
datasetUsage.getDatasetFromMemory(key).setDataItem(lastIndex, dataItems.get(last));
return true;
} else
{
int index = 0;
for (int i = 0; i <= last; i++)
{
if (oldItem.compareTo(dataItems.get(i)) == 0)
{
index = i;
break;
}
}
datasetUsage.getDatasetFromMemory(key).setDataItem(lastIndex, dataItems.get(index));
for (int i = index + 1; i <= last; i++)
datasetUsage.getDatasetFromMemory(key).addDataItem(dataItems.get(i));
return true;
}
}
private int getPeriods(Interval interval)
{
int periods = refreshInterval / interval.getLengthInSeconds();
if (periods > 10) periods += 5;
else if (periods < 10) periods = 10;
return periods;
}
private String getFavoritesDataURL(Stock stock)
{
String url = NbBundle.getMessage(
getClass(), "favorites.data.url",
new Object[]
{
ACCESS_KEY, stock.getSymbol()
});
return url;
}
private String getDataURL(Stock stock, Interval interval)
{
String url = NbBundle.getMessage(
getClass(), "data.url",
new Object[]
{
ACCESS_KEY, Integer.toString(interval.getLengthInSeconds()), stock.getSymbol()
});
return url;
}
private String getLastDataURL(int period, Stock stock, Interval interval)
{
String url = NbBundle.getMessage(
getClass(), "last.data.url",
new Object[]
{
ACCESS_KEY, Integer.toString(period), Integer.toString(interval.getLengthInSeconds()), stock.getSymbol()
});
return url;
}
@Override
protected Dataset fetchDataForFavorites(Stock stock)
throws IOException, ParseException
{
synchronized ((stock.toString() + "-" + DAILY.getTimeParam()).intern())
{
Dataset result = null;
List<DataItem> items = new ArrayList<DataItem>();
BufferedReader bufferedReader = null;
String uri = getFavoritesDataURL(stock);
bufferedReader = ProxyManager.getDefault().bufferReaderGET(uri);
String inputLine;
boolean startOnNext = false;
while ((inputLine = bufferedReader.readLine()) != null)
{
if (inputLine.contains("Accesses remaining in this period"))
{
String accesses = inputLine.split(",", 2)[1].replace("\"", "");
accessesRemaining = Integer.parseInt(accesses);
if (accessesRemaining < 1)
{
NotifyUtil.warn("Accesses remaining", "You have no more accesses remaining", false);
return null;
}
}
if (inputLine.equals("QUOTE END"))
{
startOnNext = false;
break;
}
if (startOnNext)
{
String[] values = inputLine.split(",");
if (values.length > 6)
{
long time = Long.parseLong(values[2]) * 1000;
double open = Double.parseDouble(values[3]);
double high = Double.parseDouble(values[4]);
double low = Double.parseDouble(values[5]);
double close = Double.parseDouble(values[6]);
double volume = 0d;
DataItem item = new DataItem(time, open, high, low, close, volume);
items.add(item);
}
}
if (inputLine.equals("QUOTE START"))
{
startOnNext = true;
continue;
}
}
Collections.sort(items);
result = new Dataset(items);
bufferedReader.close();
return result;
}
}
@Override
protected Dataset fetchData(Stock stock, Interval interval)
throws IOException, ParseException
{
synchronized ((stock.toString() + "-" + interval.getTimeParam()).intern())
{
Dataset result = null;
List<DataItem> items = new ArrayList<DataItem>();
BufferedReader bufferedReader = null;
String uri = getDataURL(stock, interval);
bufferedReader = ProxyManager.getDefault().bufferReaderGET(uri);
String inputLine;
boolean startOnNext = false;
while ((inputLine = bufferedReader.readLine()) != null)
{
if (inputLine.contains("Accesses remaining in this period"))
{
String accesses = inputLine.split(",", 2)[1].replace("\"", "");
accessesRemaining = Integer.parseInt(accesses);
if (accessesRemaining < 1)
{
NotifyUtil.warn("Accesses remaining", "You have no more accesses remaining", false);
return null;
}
}
if (inputLine.equals("QUOTE END"))
{
startOnNext = false;
break;
}
if (startOnNext)
{
String[] values = inputLine.split(",");
if (values.length > 6)
{
long time = Long.parseLong(values[2]) * 1000;
double open = Double.parseDouble(values[3]);
double high = Double.parseDouble(values[4]);
double low = Double.parseDouble(values[5]);
double close = Double.parseDouble(values[6]);
double volume = 0d;
DataItem item = new DataItem(time, open, high, low, close, volume);
items.add(item);
}
}
if (inputLine.equals("QUOTE START"))
{
startOnNext = true;
continue;
}
}
Collections.sort(items);
result = new Dataset(items);
bufferedReader.close();
return result;
}
}
@Override
protected String fetchCompanyName(String symbol)
throws InvalidStockException, StockNotFoundException, RegistrationException, IOException
{
return symbol;
}
@Override
public String getRegistrationMessage()
{
return NbBundle.getMessage(ForexFeedChartsy.class, "registration.msg");
}
@Override
public String getRegistrationURL()
{
return NbBundle.getMessage(ForexFeedChartsy.class, "registration.url");
}
private static final long serialVersionUID = SerialVersion.APPVERSION;
private String ACCESS_KEY = "";
private int refreshInterval;
private int accessesRemaining = 0;
private static final Interval[] supportedIntervals =
{
new CustomInterval("5 Sec", true, 0, "5S", 5),
new CustomInterval("10 Sec", true, 0, "10S", 10),
new CustomInterval("30 Sec", true, 0, "30S", 30),
new CustomInterval("45 Sec", true, 0, "45S", 45),
new CustomInterval("1 Min", true, 0, "1M", 60),
new CustomInterval("5 Min", true, 0, "5M", 300),
new CustomInterval("10 Min", true, 0, "10M", 600),
new CustomInterval("15 Min", true, 0, "15M", 900),
new CustomInterval("20 Min", true, 0, "20M", 1200),
new CustomInterval("30 Min", true, 0, "30M", 1800),
new CustomInterval("45 Min", true, 0, "45M", 2700),
new CustomInterval("1 Hour", true, 0, "1H", 3600),
new CustomInterval("2 Hour", true, 0, "2H", 7200),
new CustomInterval("3 Hour", true, 0, "3H", 10800),
new CustomInterval("4 Hour", true, 0, "4H", 14400),
new CustomInterval("6 Hour", true, 0, "6H", 21600),
new CustomInterval("12 Hour", true, 0, "12H", 43200)
};
}